const express = require('express');
const cors = require('cors');
const helmet = require('helmet');
const compression = require('compression');
const mongoSanitize = require('express-mongo-sanitize');
const xss = require('xss-clean');
const rateLimit = require('express-rate-limit');
const morgan = require('morgan');
const path = require('path');
const passport = require('passport');
const httpStatus = require('http-status');

// 导入中间件
const { errorConverter, errorHandler } = require('./middleware/error');
const { authLimiter } = require('./middleware/rateLimiter');
const { activityLogger } = require('./middleware/activityLogger.middleware');
const routes = require('./routes');
const config = require('./config/config');
const logger = require('./config/logger');
const ApiError = require('./utils/ApiError');
const backupService = require('./services/backup.service');

// 初始化Express应用
const app = express();

// 如果在生产环境中，通过代理
if (config.env === 'production') {
  app.set('trust proxy', 1);
}

// 日志中间件
if (config.env !== 'test') {
  app.use(morgan('combined', { stream: { write: (message) => logger.info(message.trim()) } }));
}

// 设置安全HTTP头
app.use(helmet());

// JSON解析
app.use(express.json());

// URL编码表单解析
app.use(express.urlencoded({ extended: true }));

// 压缩所有响应
app.use(compression());

// CORS设置
app.use(cors());
app.options('*', cors());

// 数据净化
app.use(mongoSanitize());

// XSS防护
app.use(xss());

// 身份验证
app.use(passport.initialize());
require('./config/passport');

// 限制请求以防DDoS攻击
if (config.env === 'production') {
  app.use('/api/auth', authLimiter);
}

// 为上传的头像文件添加特殊的CORS和Cross-Origin-Resource-Policy头部
// 这对解决跨域图片加载问题至关重要
app.use('/uploads/avatars', (req, res, next) => {
  // 允许所有源访问，或者替换为您的前端域名如 'http://localhost:5173'
  res.setHeader('Access-Control-Allow-Origin', '*');
  // 允许资源被任何源使用，避免 ERR_BLOCKED_BY_RESPONSE.NotSameOrigin 错误
  res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
  res.setHeader('Access-Control-Allow-Methods', 'GET, HEAD');
  // 缓存预检请求结果5分钟
  res.setHeader('Access-Control-Max-Age', '300');
  next();
});

// 启用静态文件服务，提供上传的头像文件访问
app.use(express.static(path.join(__dirname, '../public')));

// 用户活动日志记录中间件
// 注意：此中间件应在API路由之前加载，以捕获所有API请求
app.use('/api', activityLogger({
  // 忽略不需要记录的路径
  ignorePaths: [
    '/api/docs',
    '/api/health',
    '/api/activity-logs'  // 避免记录活动日志API自身的访问
  ],
  // 是否记录请求体和响应体(敏感操作可能需要记录)
  logBody: false
}));

// API路由
app.use('/api', routes);

// 添加路由调试端点
app.get('/debug-routes', (req, res) => {
  const routes = [];
  // 获取所有注册的路由
  app._router.stack.forEach((middleware) => {
    if (middleware.route) {
      // 直接在app上定义的路由
      routes.push({
        path: middleware.route.path,
        methods: Object.keys(middleware.route.methods).filter(method => middleware.route.methods[method]),
        stack: middleware.route.stack.map(h => h.name || 'anonymous')
      });
    } else if (middleware.name === 'router') {
      // 路由器中定义的路由
      middleware.handle.stack.forEach((handler) => {
        if (handler.route) {
          routes.push({
            path: handler.route.path,
            router: middleware.regexp.toString(),
            methods: Object.keys(handler.route.methods).filter(method => handler.route.methods[method]),
            stack: handler.route.stack.map(h => h.name || 'anonymous')
          });
        }
      });
    }
  });
  
  res.json({
    error: 0,
    body: { routes, total: routes.length },
    message: '获取路由配置成功'
  });
});

// 处理404错误
app.use((req, res, next) => {
  next(new ApiError(httpStatus.NOT_FOUND, '找不到请求的资源'));
});

// 错误转换
app.use(errorConverter);

// 错误处理
app.use(errorHandler);

// 启动自动备份调度器
if (config.env !== 'test') {
  // 在应用启动后初始化备份调度器
  app.once('ready', async () => {
    try {
      logger.info('正在初始化数据库备份调度器...');
      await backupService.startBackupScheduler();
      logger.info('数据库备份调度器初始化完成');
    } catch (error) {
      logger.error('初始化数据库备份调度器失败:', error);
    }
  });
}

module.exports = app; 